package com.alien.admin.modules.gitlab.service.impl;

import com.alien.admin.modules.deploy.domain.DpServer;
import com.alien.admin.modules.gitlab.service.GitlabService;
import com.alien.admin.modules.gitlab.service.dto.MergeBranch;
import com.alien.admin.modules.gitlab.service.utils.EnvUtils;
import com.alien.admin.modules.gitlab.service.utils.GitLabServiceUtils;
import com.alien.admin.modules.security.service.dto.JwtUserDto;
import com.alien.admin.utils.FileUtil;
import com.alien.admin.utils.SecurityUtils;
import org.gitlab4j.api.GitLabApiException;
import org.gitlab4j.api.models.Branch;
import org.gitlab4j.api.models.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

@Service
public class GitlabServiceImpl implements GitlabService {
    @Autowired
    private GitLabServiceUtils gitLabServiceUtils;

    @Autowired
    private EnvUtils envUtils;

    private String getPrivateToken() {
        final JwtUserDto jwtUserDto = (JwtUserDto) SecurityUtils.getCurrentUser();
        return jwtUserDto.getUser().getGitlabToken();
    }

    private String getLoginUserName() {
        final JwtUserDto jwtUserDto = (JwtUserDto) SecurityUtils.getCurrentUser();
        return jwtUserDto.getUser().getNickName();
    }

    @Override
    public List<Branch> queryBranchList(DpServer dpServer) throws GitLabApiException {
        Long projectId = dpServer.getProjectId();
        List<Branch> branchList = gitLabServiceUtils.getBranches(getPrivateToken(), Integer.valueOf(projectId.intValue()));

        // 过滤统一合并分支
        List<String> mergeBranchList = envUtils.getMergeBranchList();
        return branchList.stream().filter(branch -> (mergeBranchList.indexOf(branch.getName()) < 0)).collect(Collectors.toList());
    }

    @Override
    public List<Tag> queryTagList(DpServer dpServer) throws GitLabApiException {
        Long projectId = dpServer.getProjectId();
        List<Tag> tagList = gitLabServiceUtils.getTags(getPrivateToken(), Integer.valueOf(projectId.intValue()));
        return tagList;
    }

    @Override
    public String mergeBranch(MergeBranch mergeBranch) throws GitLabApiException {
        return mergeBranch(getPrivateToken(), mergeBranch);
    }

    @Override
    public void rollbackBranch(String branchName, String env, Integer projectId) throws GitLabApiException {
        rollbackBranch(getPrivateToken(), branchName, env, projectId);
    }

    @Override
    public String mergeBranch(String privateToken, MergeBranch mergeBranch) throws GitLabApiException {
        Integer projectId = Integer.valueOf(mergeBranch.getProjectId().intValue());

        // 获取待合并分支
        String envBranchName = envUtils.getEnvStandardBranch(mergeBranch.getEnv());
        try {
            gitLabServiceUtils.getBranch(privateToken, projectId, envBranchName);
        } catch (GitLabApiException ex) {
            // 目標分支不存在，從mater創建
            gitLabServiceUtils.createBranch(privateToken, projectId, envBranchName, "master");
        }

        String user = getLoginUserName();
        StringBuilder comment = new StringBuilder();
        comment.append("操作用户[").append(user).append("]合并代码");

        // 如果允许分支回退，则需要将统一分支做备份后再合并
        String sourceBranch = mergeBranch.getSource();
        if(mergeBranch.getEnableRollback()) {
            String envBranchBackup = getEnvBackupBranch(envBranchName, sourceBranch);
            gitLabServiceUtils.createBranch(privateToken, projectId, envBranchBackup, envBranchName);
        }

        gitLabServiceUtils.merge(privateToken, projectId, sourceBranch, envBranchName, comment.toString());

        return envBranchName;
    }

    @Override
    public void rollbackBranch(String privateToken, String branchName, String env, Integer projectId) throws GitLabApiException {
        // 查找备份分支是否存在
        String envBranchName = envUtils.getEnvStandardBranch(env);
        String envBranchBackup = getEnvBackupBranch(envBranchName, branchName);
        if(isBranchExist(privateToken, projectId, envBranchBackup)) {
            // 回滾-刪除統一分支
            gitLabServiceUtils.deleteBranch(privateToken, projectId, envBranchName);

            // 回滾，從备份分支重新创建统一分支
            gitLabServiceUtils.createBranch(privateToken, projectId, envBranchName, envBranchBackup);
            // 删除备份分支
            gitLabServiceUtils.deleteBranch(privateToken, projectId, envBranchBackup);
        }
    }

    String getEnvBackupBranch(String envBranchName, String branchName) {
        String featureMd5 = FileUtil.getMd5(branchName.getBytes());
        String branchBackup = String.format("%s_%s", envBranchName, featureMd5);
        return branchBackup;
    }

    private boolean isBranchExist(String privateToken, Integer projectId, String branchName) {
        try {
            gitLabServiceUtils.getBranch(privateToken, projectId, branchName);
        } catch (GitLabApiException e) {
            return false;
        }

        return true;
    }

    @Override
    public void deleteBranch(String privateToken, Integer projectId, String env, String branchName) throws GitLabApiException {
        String envBranchName = envUtils.getEnvStandardBranch(env);
        String envBranchBackup = getEnvBackupBranch(envBranchName, branchName);
        gitLabServiceUtils.deleteBranch(privateToken, projectId, envBranchBackup);
    }
}
